<template>
  <div>
     <div class="login">
            <div class="main">
                <div class="main-title">
                    <span>音视频通信</span>
                </div>
                <div class="main-input">
                    <input type="text" placeholder="请输入房间号">
                </div>
                <div class="main-button">
                    <button>进入房间</button>
                </div>
            </div>
        </div>
        <div class="main-web" style="display: none;">
            <div class="remote-user-list">
                <h2>房间成员</h2>
                <ul class="user-ul"></ul>
            </div>
            <div class="container-box">
                <div class='local-display-name'>
                    <span class="username">User: <b></b></span>
                    <span class="channelid">Channel Id: <b></b></span>
                    <span class="streamstate">推流状态：<b></b></span>
                </div>
                <div class='publisher'>
                    <button class="select-preview">关闭预览</button>
                    <button class="push-stream">停止推流</button>&nbsp;&nbsp;
                    <span class="streamType" style="visibility: hidden;">
                        <label for="cameraPublisher">推视频流</label>
                        <input id="cameraPublisher"
                            type="radio"
                            name="streamType"
                            checked
                        />&nbsp;
                        <label for="screenPublish">推共享流</label>
                        <input
                            id="screenPublish"
                            type="radio"
                            name="streamType"
                        />
                    </span>
                </div>
                <div class='local-video'>
                    <video autoplay playsinline></video>
                </div>
            </div>

            <div class="video-container"></div>
        </div>
  </div>
</template>
<script>
  export default{
    data(){
      return{

      }
    },
    mounted() {
      var channelId;
      var userName = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
      var publisherList = [];

      /**
       * AliWebRTC isSupport检测
       */
      let aaa = new AliRtcEngine()
      aaa.isSupport().then(re => {
          console.log(re);
          init();
      }).catch(err => {
          alert(err.message);
      })

      var aliWebrtc;
      function init() {
          aliWebrtc = new AliRtcEngine("");
          /**
           * remote用户加入房间 onJoin
           * 更新在线用户列表
           */
          aliWebrtc.on('onJoin', (publisher) => {
              if(publisher.userId){
                  updateUserList();
              }
          });
          /**
           * remote流发布事件 onPublish
           * 将该用户新增到推流列表
           */
          aliWebrtc.on('onPublisher', (publisher) => {
              initialization(publisher.userId)
              console.log("onPublisher", publisher);
              let index = publisherList.getIndexByProprety(publisher.userId, "userId");
              if (index === -1) {
                  publisherList.push(publisher);
              }
          });

          /**
           * remote流结束发布事件 onUnPublisher
           * 推流列表删除该用户
           * 移除用户视图
           * 初始化订阅状态
           */
          aliWebrtc.on('onUnPublisher', (publisher) => {
              console.log('onUnPublisher',publisher);
              detelePublisher(publisher.userId);
              removeDom(publisher.userId);
              initialization(publisher.userId);
          });

          /**
           *  错误信息
           */
          aliWebrtc.on('onError', (error) => {
              console.warn('error',error);
              var msg = error && error.message ? error.message : error;
              if (msg && msg.indexOf('no session') > -1) {
                  msg = "请重新登录：" + msg;
              }
              if (msg && msg.indexOf('screen share error') > -1) {
                  msg = "屏幕共享已取消";
              }

              if(error.code == 15) {
                  msg = "没有开启H5兼容";
              }
              if(error.type === "publish") {
                  console.log("推流断开 需要停止推流");
                  $(".push-stream").click();
              }
              if(error.type === "subscribe") {
                  console.log("订阅断开 取消订阅该userId的所有订阅并移除所有该userId的dom")
                  aliWebrtc.unSubscribe(error.userId).then(re => {
                      console.log("订阅断开 取消订阅成功");
                  }).catch(err => console.log("订阅断开 取消订阅失败", err))

                  detelePublisher(error.userId);
                  removeDom(error.userId);
              }
              alert(msg);

          });

          /**
           * 检测到用户离开频道
           * 更新用户列表
           * 移除用户视图
           */
          aliWebrtc.on('onLeave', (publisher) => {
              initialization(publisher.userId);

              updateUserList();
              removeDom(publisher.userId);
          })
      }

      /**
       * 加入房间
       * 触发：输入房间号、单击加入房间按钮
       * 更新页面信息
       * 默认开启预览
       * 获取鉴权信息
       * 加入房间
       * 本地默认自动推视频流（视频流 + 音频流）
       * 发布本地流
       */
      function joinroom() {
          $('.local-display-name .username b').text(userName);
          $('.local-display-name .channelid b').text(channelId);
          $('.local-display-name .streamstate b').text('当前未推流');
          //1.预览
          var localVideo = $('.local-video video');
          aliWebrtc.startPreview(localVideo[0]).then((obj) => {
              }).catch((error) => {
              alert(error.message);
          });
          //2. 获取频道鉴权令牌参数 -->
          getRTCAuthInfo().then((authInfo) => {
              console.log(authInfo,"authInfo");
              //3. 加入房间 默认推音频视频流
              aliWebrtc.joinChannel(authInfo, userName).then(() => {
                  console.log('加入房间成功');
                  // 4. 发布本地流
                  aliWebrtc.configLocalAudioPublish = true;
                  aliWebrtc.configLocalCameraPublish = true;
                  aliWebrtc.publish().then((res) => {
                      console.log('发布流成功');
                      $('.local-display-name .streamstate b').text('视频流');
                  }, (error) => {
                      alert(error.message);
                  });
              }).catch((error) => {
                  alert(error.message);
              })
          }).catch((error) => {
              alert(error.message);
          });
      }

      /**
       * 更新在线用户列表
       */
      var updateUserList = () => {
          $('.user-ul').empty();
          let userList = aliWebrtc.getUserList();
          let frg = document.createDocumentFragment();
          userList.map((user) => {
              let html = $('<li class="user-ul-li">' + user.displayName + '<ul class="menu"></ul></li>');
              $(html).bind('mouseover',user.userId,showUserMenu).bind('mouseleave',hideUserMenu);
              frg.append(html[0]);
          })
          $('.user-ul').append($(frg));
      }



      /**
       * 获取频道鉴权令牌参数这个方法需要客户重新实现，调用RTC服务的Open API获取
       */
      var getRTCAuthInfo = () => {
          return new Promise(function (resolve, reject) {
              $.ajax({
                  url: "${ctx}/ddd/createToken?room=" + channelId + "&user=" + userName + "&passwd=1234",
                  type: 'POST',
                  contentType: 'application/json; charset=utf-8',
                  dataType: 'json',
                  success: (data) => {
                      data.data.channel = channelId;
                      resolve(data.data);
                  },
                  failed: (error) => {
                      reject(error);
                  }
              });
          });
      }

      /**
       * 获取当前remote用户的流菜单
       */
      var showUserMenu = (evt) => {
          let userId = evt.data
          if(!$(event.target).eq(0).hasClass('user-ul-li')){
              return
          }
          $('.menu').hide();
          $(event.target).find('.menu').empty().show();
          let userInfo = aliWebrtc.getUserInfo(userId);
          let streamTypeList = userInfo.streamConfigs.filter(item => {
              return item.state === "active";
          });
          var html = ""
          if(streamTypeList.length == 0){
              html = $('<li>该用户未推流</li>')
              $(event.target).find('.menu').append(html[0])
          }else{
              var frg = document.createDocumentFragment()
              streamTypeList.map(item => {
                  item.userId = userId
                  var labelName = ""
                  if(item.type === "video"){
                      switch (item.label) {
                          case "sophon_video_camera_large":
                              labelName = "视频流";
                              break;
                          case "sophon_video_screen_share":
                              labelName = "共享流";
                              break;
                          case "sophon_audio":
                              labelName = "";
                              break;
                          default:
                              labelName = "";
                      }
                  } else {
                      labelName = "";
                  }
                  //将音频流或小流的标签不显示
                  if(labelName !== ""){
                      let subState = item.subscribed === true ? "取消订阅" : "订阅"
                      html = $('<li>'+ labelName +'&nbsp;<span>'+ subState +'</span></li>')
                      $(html).find('span').off("click").on("click", item, unSub)
                      frg.append(html[0])
                  }
              })
              $(event.target).find('.menu').append($(frg))
          }
      }

      /**
       * 隐藏当前remote用户的流菜单
       */
      var hideUserMenu = () => {
          $(event.currentTarget).find('.menu').hide()
      }

      /**
       * 订阅&取消订阅
       */
      var unSub = (evt) => {
          let v = evt.data
          console.log(v)
          if(v.subscribed){
              setConfigRemote(v.userId, v.label).then(re => {
                  removeDom(v.userId, v.label)
                  console.log('取消订阅')
              });
          }else {
              receivePublishManual(v).then(re => {
                  creatDomAndshowRemoteVideo(v)
                  console.log('订阅成功')
              });
          }
          $('.menu').hide()
      }


      /**
       * 获取dom标签 设置video
       */
      var creatDomAndshowRemoteVideo = (v) => {
          var dom = getDisplayRemoteVideo(v.userId, v.label)
          if (v.label != "sophon_video_screen_share") {
              aliWebrtc.setDisplayRemoteVideo(v.userId, dom, 1);
          } else {
              aliWebrtc.setDisplayRemoteVideo(v.userId, dom, 2);
          }
      }

      /**
       * 创建获取订阅的remote的video标签
       */
      var getDisplayRemoteVideo = function (userId, label) {
          var label = label === 'sophon_video_camera_large' ? 'camera' : 'screen'
          var id = userId + '_' + label;
          var videoWrapper = $('#' + id);
          if (videoWrapper.length == 0) {
              var userInfo = aliWebrtc.getUserList().filter(item => {
                  return item.userId === userId;
              })
              var displayName = userInfo[0].displayName;
              videoWrapper = $('<div class="remote-subscriber" id=' + id + '> <video autoplay playsinline></video><div class="display-name"></div></div>');
              $('.video-container').append(videoWrapper);

          }
          videoWrapper.find('.display-name').text(displayName);
          return videoWrapper.find('video')[0];
      }

      /**
       * 移除dom
       */
      var removeDom = (userId, label) => {
          if(userId) {
              if(!label){
                  $("#" + userId + "_camera").remove();
                  $("#" + userId + "_screen").remove();
              }else {
                  label = label === 'sophon_video_camera_large' ? 'camera' : 'screen'
                  $("#" + userId + "_" + label).remove();
              }
          }
      }

      /**
       * 取消订阅设置
       */
      var setConfigRemote = (userId, label) => {
          return new Promise((resolve, reject) => {
              //demo中只订阅大流
              if (label === "sophon_video_camera_large") {
                  aliWebrtc.configRemoteCameraTrack(userId, false, false);
                  aliWebrtc.configRemoteAudio(userId,false)
              } else if (label === "sophon_video_screen_share") {
                  aliWebrtc.configRemoteScreenTrack(userId, false);
              }
              aliWebrtc.subscribe(userId).then(re => {
                      resolve();
                  }).catch(err => console.log("取消订阅失败", err))
              });
      }



      /**
       * 订阅设置
       */
      var receivePublishManual = (v)  =>{
          console.log("receivePublishManual订阅", v);
          return new Promise((resolve, reject) => {
              if (v.label === "sophon_video_camera_large") {
                  console.log("订阅固定视频流");
                  aliWebrtc.configRemoteCameraTrack(v.userId, true, true);
                  aliWebrtc.configRemoteAudio(v.userId, true);
              } else if (v.label === "sophon_video_screen_share") {
                  console.log("订阅屏幕共享流");
                  aliWebrtc.configRemoteScreenTrack(v.userId, true);
              }
              aliWebrtc.subscribe(v.userId).then(re => {
                  resolve();
              }).catch((err) => {
                  reject(err);
                  alert(err.message);
              });
          })
      }

      /**
       * 用户停止推流时 删除用户列表中该用户
       */
      var detelePublisher = (userId) => {
          let index = publisherList.getIndexByProprety(userId, "userId");
          if (index != -1) {
            publisherList.splice(index, 1);
            this.detelePublisher(userId);
          } else {
            console.log("未找到之前的推流数据"); //删除推流用户
          }
      }

      /**
       * 进入房间
       */
      $('.main-button button').click(() => {
          var value = $('.main-input input').val();
          if(!value){
              alert('请输入房间号')
              return
          }
          channelId = value
          joinroom()
          $('.login').hide()
          $('.main-web').show()
      })

      /**
       * 控制预览
       */
      $('.publisher .select-preview').click(function(e) {
          var localVideo = $('.local-video video');
          if($(this).text() === '开启预览'){
              $(this).text('处理中...')
              aliWebrtc.startPreview(localVideo[0]).then((obj) => {
                  setTimeout(() => {
                      $(this).text('关闭预览')
                  },2500)
              }).catch((error) => {
                  setTimeout(() => {
                      $(this).text('开启预览')
                  },2500)
                  alert(error.message);
              });
          }else if($(this).text() === '关闭预览') {
              $(this).text('处理中...')
              aliWebrtc.stopPreview().then((re) => {
                  setTimeout(() => {
                      $(this).text('开启预览')
                  },2500)
              }).catch((error) => {
                  setTimeout(() => {
                      $(this).text('关闭预览')
                  },2500)
                  alert(error.message);
              });
          }else {
              return
          }
      })

      /**
       * 控制推流选项
       */
      $('.publisher .streamType input').click(function(e) {
          var config = $(this).attr('id')
          if(config === 'cameraPublisher'){
              aliWebrtc.configLocalAudioPublish = true
              aliWebrtc.configLocalCameraPublish = true
              aliWebrtc.configLocalScreenPublish = false
          }else {
              aliWebrtc.configLocalAudioPublish = false
              aliWebrtc.configLocalCameraPublish = false
              aliWebrtc.configLocalScreenPublish = true
          }
      })

      /**
       * 处理推流
       */
      $('.publisher .push-stream').click(function(e) {
          if($(this).text() === "开始推流") {
              $(this).text("处理中...")
              aliWebrtc
                  .publish()
                  .then(re => {
                      setTimeout(() => {
                          $(".streamType").css({
                              visibility: "hidden"
                          })
                          $(this).text("停止推流")
                          if(aliWebrtc.configLocalScreenPublish) {
                              $('.local-display-name .streamstate b').text('共享流')
                          } else {
                              $('.local-display-name .streamstate b').text('视频流')
                          }
                      },3500)
                  })
                  .catch(err => {
                      console.log(err.message)
                  });

          }else if($(this).text() === "停止推流") {
              $(this).text("处理中...")
              aliWebrtc.unPublish().then((re)=>{
                  setTimeout(() => {
                      $(".streamType").css({
                          visibility: "visible"
                      })
                      $(this).text("开始推流")
                      $('.local-display-name .streamstate b').text('当前未推流')
                  },3500)
              } ,(err)=>{
                  console.log(err.message);
              });
          }else {
              return
          }
      });

      /**
       * 页面刷新时调用离会
       */
      window.onbeforeunload = function (e) {
          aliWebrtc.leaveChannel();
          aliWebrtc.dispose();
      };
      // var aliWebrtc
      // try{
      //   aliWebrtc = new AliRtcEngine();
      //   console.log("成功")
      // }catch(error){
      //   console.log(error)
      //   alert("请从官网下载最新SDK，添加到同层目录，取消第11行注释")
      // }
      // aliWebrtc.isSupport().then((res)=>{
      //   //支持webrtc
      //   console.log("支持")
      // }).catch((error)=>{
      // 	//不支持webrtc
      //   console.log("不支持")
      // })
    },
    methods:{

    }
  }
</script>

<style>

  ul,li{
    padding: 0;
    margin: 0;
    list-style: none;
  }

  .login
  {
    min-height: 100vh;
    position: relative;
    background-color: #006eff;
  }

  .login .main
  {
    width: 420px;
    background-color: #fff;
    padding: 30px 26px 24px 26px;
    box-sizing: border-box;
    position: absolute;
    top: 40%;
    left: 50%;
    -webkit-transform: translate(-50%, -60%);
    transform: translate(-50%, -50%);
    font-size: 14px;
  }

  .main .main-title
  {
    font-size: 30px;
    text-align: center;
    color: #333;
    letter-spacing: 1px;
  }

  .main .main-input
  {
    margin: 33px 0 13px 0;
  }

  .main-input input
  {
    padding: 0 14px;
    width: 100%;
    box-sizing: border-box;
    line-height: 38.5px;
    height: 38.5px;
    color: #888;
    border: solid 1px #ddd;
    position: relative;
    margin-bottom: 10px;
    touch-action: none;
  }

  .main .main-button button
  {
    padding: 0 14px;
    width: 100%;
    box-sizing: border-box;
    line-height: 38.5px;
    height: 38.5px;
    background-color: #006eff;
    border: solid 1px #006eff;
    color: white;
    letter-spacing: 1px;
  }

  .container-box
  {
    margin-left: 200px;
    margin-right: 300px;
    position: relative;
  }

  .local-video
  {
    margin: 0 calc(50 / 1080 * 100vh);
    position: relative;
  }

  .local-video video{
    height: calc(602 / 850 * 100vh);
    width: 100%;
    display: block;
    background-color: black;
  }

  .remote-user-list
  {
    position: absolute;
    left: 0;
    top: 0;
    width: 200px;
    height: 100%;
    background: #333;
    color: #fff;
  }

  .remote-user-list h2{
    font-size: 20px;
    line-height: 36px;
    font-weight: weight;
    text-align: center;
  }

  .remote-user-list .user-ul
  {
    display: block;
  }

  .remote-user-list .user-ul .user-ul-li
  {
    position: relative;
    font-size: 20px;
    height: 40px;
    line-height: 40px;
    text-align: center;
  }

  .remote-user-list .user-ul .user-ul-li:hover
  {
    background: #666;
  }

  .remote-user-list .menu
  {
    position: absolute;
    z-index: 100;
    left: 200px;
    text-align: left;
    top: 1px;
    background-color: #333333;
    border-radius: 8px;
  }

  .remote-user-list .menu li
  {
    padding: 0 10px;
    min-width: 165px;
    height: 40px;
    line-height: 40px;
    color: #ddd;
    text-indent: 10px;
    cursor: pointer;
  }

  .remote-user-list .menu li span
  {
    cursor: pointer;
  }

  .remote-user-list .menu li span:hover
  {
    color: #38f;
  }

  .local-display-name
  {
    height: 50px;
    background: #333;
    width: 100%;
    /* position: absolute; */
    color: #fff;
    font-weight: normal;
  }

  .local-display-name span
  {
    margin: 0 30px;
    line-height: 50px;
    font-size: 15px;
  }

  .publisher
  {
    margin: 20px 0 20px calc(50 / 1080 * 100vh);
  }

  .publisher input[type=text]
  {
    border: 2px solid #456879;
    border-radius: 10px;
    height: 40px;
    width: 95px;
  }

  .publisher button {
    font-family: arial;
    color: #ffffff !important;
    font-size: 12px;
    width: 68px;
    height: 26px;
    background: deepskyblue;
    border: none;
    outline: none;
  }
  .publisher button:hover {
    background: #006eff;
    cursor:pointer;
  }
  .streamType labeL{
    font-family: arial;
    font-size: 16px;
  }

  .video-container
  {
    position: absolute;
    top: 0px;
    right: 0px;
    bottom: 0px;
    width: 260px;
    background-color: #eee;
    color: #fff;
    padding: 20px;
    overflow-y: scroll;
  }
  .video-container::-webkit-scrollbar {
    display: none;
  }

  .video-container .remote-subscriber
  {
    margin: 10px 0;
    position: relative;
  }
  .video-container video
  {
    background: #000;
    width: 100%;
    height: 195px;
  }

  .video-container .display-name
  {
    position: absolute;
    top: 35px;
    left: 30px;
    padding: 5px;
    background: rgba(0,0,0,0.1);
    color: white;
  }

  .alert {
    display: none;
    position: fixed;
    top: 8%;
    left: 50%;
    min-width: 300px;
    max-width: 600px;
    transform: translateX(-50%);
    z-index: 99999;
    text-align: center;
    padding: 10px 15px;
    border-radius: 3px;
  }

  .alert-success {
      color: #3c763d;
      background-color: #dff0d8;
      border-color: #d6e9c6;
  }

  .alert-info {
      color: #31708f;
      background-color: #d9edf7;
      border-color: #bce8f1;
  }

  .alert-warning {
      color: #8a6d3b;
      background-color: #fcf8e3;
      border-color: #faebcc;
  }

  .alert-danger {
      color: #a94442;
      background-color: #f2dede;
      border-color: #ebccd1;
  }
</style>
